package com.lovenote.common.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.lovenote.common.dto.CatalogDto;
import com.lovenote.common.dto.NoteDto;
import com.lovenote.common.pojo.Note;
import com.lovenote.common.pojo.NoteCatalog;
import com.lovenote.common.pojo.User;
import com.lovenote.common.service.INoteCatalogService;
import com.lovenote.common.service.INoteService;

@Controller
public class NoteController {
	
	@Autowired
	@Qualifier("noteCatalogService")
	private INoteCatalogService noteCatalogService;
	
	@Autowired
	@Qualifier("noteService")
	private INoteService noteService;
	
	/**
	 * Handle get catalog list request
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/note/catalogs", method = RequestMethod.GET)
	private String catalogs (Model model, HttpServletRequest request) {
		User user = (User) request.getSession().getAttribute("user");
		List<NoteCatalog> noteCatalogs = this.noteCatalogService.getNoteCatalogList(user.getId());
		if (noteCatalogs.size() > 0) {
			model.addAttribute("noteCatalogs", noteCatalogs);
			model.addAttribute("isNoteCatalogs", true);
		} else {
			model.addAttribute("isNoteCatalogs", false);
		}
		return "note/catalogs";
	}
	
	/**
	 * Handle modify catalog request
	 * @param model
	 * @param id
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/note/catalogs/modify/{id}", method = RequestMethod.GET)
	private String modifyCatalog (Model model, @PathVariable int id, HttpServletRequest request) {
		User user = (User) request.getSession().getAttribute("user");
		List<NoteCatalog> noteCatalogs = this.noteCatalogService.getNoteCatalogList(user.getId());
		if (noteCatalogs.size() > 0) {
			model.addAttribute("noteCatalogs", noteCatalogs);
			model.addAttribute("isNoteCatalogs", true);
			for (NoteCatalog catalog : noteCatalogs) {
				if (catalog.getId() == id) {
					model.addAttribute("catalog", catalog);
					return "note/modify_catalog";
				}
			}
		}
		return "note/catalogs";
	}
	
	/**
	 * Handle add catalog request
	 * @param model
	 * @param catalogDto
	 * @param result
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/note/catalogs/add", method = RequestMethod.POST)
	private Map<String, Object> addCatalog (Model model, @ModelAttribute("catalogDto") @Valid CatalogDto catalogDto, BindingResult result, HttpServletRequest request) {
		Map<String, Object> message = new HashMap<String, Object>(); 
		User user = (User) request.getSession().getAttribute("user");
		
		// Verify if the name is unique
		if (this.noteCatalogService.isNameUnique(user.getId(), catalogDto.getName())) {
			result.rejectValue("name", null, "分类名\""+ catalogDto.getName() +"\"已经存在,请换一个");
		} 
		
		// Check errors
		if (result.hasErrors()) {
			List<FieldError> errors = result.getFieldErrors();				// Get errors
			List<String> errorList = new ArrayList<String>();
			for (FieldError error : errors) {
				errorList.add(error.getDefaultMessage());
			}
			message.put("result", false);
			message.put("error", errorList);
		} else {
			NoteCatalog noteCatalog = new NoteCatalog();
			noteCatalog.setUserId(user.getId());
			noteCatalog.setName(catalogDto.getName());
			if (catalogDto.getOrderId() != null) 
				noteCatalog.setOrderId(catalogDto.getOrderId());
			this.noteCatalogService.save(noteCatalog);
			message.put("result", true);
		}
		return message;
	}
	
	/**
	 * Handle modify catalog request
	 * @param model
	 * @param id
	 * @param catalogDto
	 * @param result
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/note/catalogs/modify/{id}", method = RequestMethod.POST)
	private Map<String, Object> modifyCatalogAction (Model model, @PathVariable int id, @ModelAttribute("catalogDto") @Valid CatalogDto catalogDto, BindingResult result, HttpServletRequest request) {
		Map<String, Object> message = new HashMap<String, Object>();
		User user = (User) request.getSession().getAttribute("user");
		
		if (result.hasErrors()) {
			List<FieldError> errors = result.getFieldErrors();
			List<String> errorList = new ArrayList<String>();
			for (FieldError error : errors) {
				errorList.add(error.getDefaultMessage());
			}
			message.put("result", false);
			message.put("error", errorList);
		} else {
			NoteCatalog noteCatalog = this.noteCatalogService.get(id);
			if (noteCatalog != null && noteCatalog.getUserId() == user.getId()) {
				noteCatalog.setName(catalogDto.getName());
				if (catalogDto.getOrderId() != null)
					noteCatalog.setOrderId(catalogDto.getOrderId());
				else
					noteCatalog.setOrderId(0);
				this.noteCatalogService.update(noteCatalog);
				message.put("result", true);
			} else {
				message.put("result", false);
				message.put("url", request.getContextPath() + "/note/catalogs");
			}
		}
		return message;
	}
	
	/**
	 * Handle delete catalog request
	 * @param model
	 * @param id
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/note/catalogs/delete/{id}", method = RequestMethod.GET)
	private Map<String, Object> deleteCatalogAction (Model model, @PathVariable("id") int id, HttpServletRequest request) {
		Map<String, Object> message = new HashMap<String, Object>();
		User user = (User) request.getSession().getAttribute("user");
		
		if (this.noteCatalogService.deleteCatalog(user.getId(), id)) {
			message.put("result", true);
		} else {
			message.put("result", false);
		}
		return message;
	}
	
	/**
	 * Handle get catalog list request
	 * @param model
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/note/catalogs/list", method = RequestMethod.GET)
	private Map<String, Object> getCatalogList (Model model, HttpServletRequest request) {
		Map<String, Object> message = new HashMap<String, Object>();
		User user = (User) request.getSession().getAttribute("user");
		
		List<NoteCatalog> catalogList = this.noteCatalogService.getNoteCatalogList(user.getId());
		if (catalogList.size() > 0) {
			StringBuilder option = new StringBuilder();
			for (NoteCatalog catalog : catalogList) {
				option.append("<div class=\"item\" data-value=\"")
					.append(catalog.getId())
					.append("\">")
					.append(catalog.getName())
					.append("</div>");
			}
			message.put("catalogList", option.toString());
			message.put("result", true);
		} else {
			message.put("result", false);
		}
		return message;
	}
	
	/**
	 * Handle add note request
	 * @param model
	 * @param noteDto
	 * @param request
	 * @param result
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/note/add", method = RequestMethod.POST)
	private Map<String, Object> addNote (Model model, @ModelAttribute("noteDto") @Valid NoteDto noteDto, HttpServletRequest request, BindingResult result) {
		Map<String, Object> message = new HashMap<String, Object>();
		User user = (User) request.getSession().getAttribute("user");
		
		// Verify note tags
		if (!StringUtils.isEmpty(noteDto.getTags())) {
			// Replace '，' to ','
			noteDto.setTags(noteDto.getTags().replace('，', ','));
			String[] tags = noteDto.getTags().split(",");
			if (tags.length > 5) {
				result.rejectValue("tags", null, "您输入的笔记标签已经超过了5个");
			}
		}
		
		// Check errors
		if (result.hasErrors()) {
			List<FieldError> errors = result.getFieldErrors();
			List<String> errorMessage = new ArrayList<String>();
			for (FieldError error : errors) {
				errorMessage.add(error.getDefaultMessage());
			}
			message.put("result", false);
			message.put("error", errorMessage);
		} else {
			// No error, save the note
			Note note = new Note();
			note.setAuthor(user.getUsername());
			note.setCatalogId(noteDto.getCatalogId());
			note.setAuthor(user.getUsername());
			note.setContent(noteDto.getContent());
			note.setDateline(new Date());
			note.setTags(noteDto.getTags());
			note.setUserId(user.getId());
			this.noteService.save(note);
			message.put("result", true);
		}
		return message;
	}
}
